######################################## Lab: Xv6 and Unix utilities ######################################## 实验一要求通读: - xv6-book 第一章 第一章内容概要 **************************************** fork 系统调用调用一次,然后分别在子 **进程** 和父进程中返回一次,子进程中返回 0,父进程中返回子进程的 PID wait 系统调用用来阻塞并等待一个子进程退出,并将子进程的 PID 写入参数中。如果调用进程没有子进程,直接返回 -1.如果父进程对子进程的 PID 不感兴趣,可以直接传入 0 exec 可以用来使用一个二进制文件替换掉当前二进制映像,替换后从新的二进制映像的 main 函数开始运行,exec 允许向新的二进制映像中传递参数: .. code-block:: c char *argv[3]; argv[0] = "echo"; argv[1] = "hello"; argv[2] = 0; exec("/bin/echo", argv); printf("exec error\n"); 程序运行时会自动打开三个文件描述符:stdin(0), stdout(1), stderr(2)。因此下面的代码可以用来将数据从 stdin 拷贝到 stdout: .. code-block:: c char buf[512]; int n; while (1) { n = read(0, buf, sizeof buf); if (n == 0) break; if (n < 0) { fprintf(2, "read error\n"); exit(1); } if (write(1, buf, n) != n) { fprintf(2, "write error\n"); exit(1); } } write 返回值为读取到的字节数。close 可以用来关闭一个 fd,而在使用 open、pipe、dup 调用时,拿到的 fd 总是最小的那个,因此可以用来进行重定向: .. code-block:: c char *argv[2]; argv[0] = "cat"; argv[1] = 0; if(fork() == 0) { close(0); open("input.txt", O_RDONLY); exec("cat", argv); } 首先将 stdin 关掉,然后再打开一个文件,这时此文件的 fd 就是 0。因而完成了重定向。 管道是一个小的内核缓冲区,此缓冲区暴露了一对文件描述符分别用来进行读和写(也就是说管道是半双工的),下面的代码演示了使用管道的向 wc 传递信息: .. code-block:: c int p[2]; char *argv[2]; argv[0] = "wc"; argv[1] = 0; pipe(p); if(fork() == 0){ // 将 p[0] 重定向到 stdin close(0); dup(p[0]); close(p[0]); close(p[1]); exec("/bin/wc", argv); }else{ // 关闭管道的读端 close(p[0]); write(p[1], "hello world\n", 12); close(p[1]); } 如果没有可用数据,read 会阻塞至有数据写入或写端被关闭,在第二种情况下,read 会返回 0 文件系统 启动 xv6 **************************************** 这个比较简单,跳过 实现 sleep **************************************** 一个入门项目,主要目的应该是为了熟悉源码,kernel/sysproc.c 中实现的 sys_sleep 是没有参数的,不知道第一个参数证明传进去的,应该是修改了栈指针。系统定义了带有参数的 sleep,可以直接调用。 .. code-block:: c #include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h" int main(int argc, char** argv){ if(argc < 2){ fprintf(2, "usage: sleep NUMBER...\n"); exit(1); } sleep(atoi(argv[1])); exit(0); } 在 Makefile 中的 UPROGS 部分将 sleep 添加进去,调用 make GRADEFLAGS=sleep grade 可以查看测试 pingpong **************************************** 练习管道。管道在 user/sh.c:100 有一个实例: